<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ArrayBuffer 和 DataView 详解</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      min-height: 100vh;
      padding: 20px;
    }

    .container {
      max-width: 1200px;
      margin: 0 auto;
      background: white;
      border-radius: 15px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
      overflow: hidden;
    }

    .header {
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      color: white;
      padding: 40px;
      text-align: center;
    }

    .header h1 {
      font-size: 2.5em;
      margin-bottom: 10px;
      font-weight: 300;
    }

    .header p {
      font-size: 1.2em;
      opacity: 0.9;
    }

    .content {
      padding: 40px;
    }

    .section {
      margin-bottom: 40px;
      padding: 30px;
      border-radius: 10px;
      background: #f8f9fa;
      border-left: 5px solid #667eea;
    }

    .section h2 {
      color: #333;
      margin-bottom: 20px;
      font-size: 1.8em;
      display: flex;
      align-items: center;
      gap: 10px;
    }

    .code-block {
      background: #2d3748;
      color: #e2e8f0;
      padding: 20px;
      border-radius: 8px;
      font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
      font-size: 14px;
      line-height: 1.6;
      overflow-x: auto;
      margin: 15px 0;
    }

    .code-comment {
      color: #68d391;
    }

    .code-string {
      color: #fbb6ce;
    }

    .code-number {
      color: #90cdf4;
    }

    .code-keyword {
      color: #f6ad55;
    }

    .code-function {
      color: #81e6d9;
    }

    .result-display {
      background: #e8f5e8;
      border: 2px solid #4caf50;
      border-radius: 8px;
      padding: 15px;
      margin: 15px 0;
      font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
      font-size: 14px;
      white-space: pre-wrap;
    }

    .error-display {
      background: #ffebee;
      border: 2px solid #f44336;
      border-radius: 8px;
      padding: 15px;
      margin: 15px 0;
      font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
      font-size: 14px;
      color: #c62828;
    }

    .btn {
      padding: 12px 24px;
      border: none;
      border-radius: 6px;
      font-size: 16px;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.3s ease;
      margin-right: 10px;
      margin-bottom: 10px;
    }

    .btn-primary {
      background: #667eea;
      color: white;
    }

    .btn-primary:hover {
      background: #5a67d8;
      transform: translateY(-2px);
    }

    .btn-secondary {
      background: #f8f9fa;
      color: #495057;
      border: 2px solid #e9ecef;
    }

    .btn-secondary:hover {
      background: #e9ecef;
    }

    .comparison-table {
      width: 100%;
      border-collapse: collapse;
      margin: 20px 0;
      background: white;
      border-radius: 8px;
      overflow: hidden;
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
    }

    .comparison-table th,
    .comparison-table td {
      padding: 15px;
      text-align: left;
      border-bottom: 1px solid #e9ecef;
    }

    .comparison-table th {
      background: #667eea;
      color: white;
      font-weight: 600;
    }

    .comparison-table tr:nth-child(even) {
      background: #f8f9fa;
    }

    .comparison-table tr:hover {
      background: #e3f2fd;
    }

    .demo-section {
      background: white;
      padding: 25px;
      border-radius: 8px;
      margin: 20px 0;
      border: 2px solid #e9ecef;
    }

    .demo-title {
      font-size: 1.3em;
      font-weight: 600;
      color: #333;
      margin-bottom: 15px;
      padding-bottom: 10px;
      border-bottom: 2px solid #667eea;
    }

    .interactive-demo {
      background: white;
      padding: 25px;
      border-radius: 8px;
      margin: 20px 0;
      border: 2px solid #e9ecef;
    }

    .input-group {
      margin-bottom: 20px;
    }

    .input-group label {
      display: block;
      margin-bottom: 8px;
      font-weight: 600;
      color: #555;
    }

    .input-group input,
    .input-group select {
      width: 100%;
      padding: 12px;
      border: 2px solid #e1e5e9;
      border-radius: 6px;
      font-size: 16px;
      font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
    }

    .input-group input:focus,
    .input-group select:focus {
      outline: none;
      border-color: #667eea;
      box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
    }

    .memory-visualization {
      background: #f8f9fa;
      border: 2px solid #e9ecef;
      border-radius: 8px;
      padding: 20px;
      margin: 20px 0;
      font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
      font-size: 12px;
    }

    .memory-row {
      display: flex;
      margin-bottom: 5px;
    }

    .memory-cell {
      width: 60px;
      height: 30px;
      border: 1px solid #ccc;
      display: flex;
      align-items: center;
      justify-content: center;
      background: white;
      margin-right: 2px;
    }

    .memory-cell.header {
      background: #667eea;
      color: white;
      font-weight: bold;
    }

    .memory-cell.data {
      background: #e8f5e8;
    }

    @media (max-width: 768px) {
      .content {
        padding: 20px;
      }

      .section {
        padding: 20px;
      }
    }
  </style>
</head>

<body>
  <div class="container">
    <div class="header">
      <h1>🔧 ArrayBuffer 和 DataView 详解</h1>
      <p>深入理解JavaScript中的二进制数据处理</p>
    </div>

    <div class="content">
      <!-- 概述 -->
      <div class="section">
        <h2>📋 概述</h2>
        <p>ArrayBuffer和DataView是JavaScript中处理二进制数据的核心API，用于在Web应用中处理文件、网络通信、图像数据等。</p>

        <table class="comparison-table">
          <thead>
            <tr>
              <th>特性</th>
              <th>ArrayBuffer</th>
              <th>DataView</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td><strong>作用</strong></td>
              <td>固定长度的原始二进制数据缓冲区</td>
              <td>ArrayBuffer的视图，提供读写方法</td>
            </tr>
            <tr>
              <td><strong>直接访问</strong></td>
              <td>❌ 不能直接读写</td>
              <td>✅ 通过方法读写</td>
            </tr>
            <tr>
              <td><strong>字节序</strong></td>
              <td>依赖TypedArray</td>
              <td>可指定大端/小端</td>
            </tr>
            <tr>
              <td><strong>数据类型</strong></td>
              <td>原始字节</td>
              <td>多种数据类型</td>
            </tr>
            <tr>
              <td><strong>灵活性</strong></td>
              <td>低</td>
              <td>高</td>
            </tr>
          </tbody>
        </table>
      </div>

      <!-- ArrayBuffer基础 -->
      <div class="section">
        <h2>🔧 ArrayBuffer 基础</h2>

        <div class="demo-section">
          <div class="demo-title">创建和使用ArrayBuffer</div>
          <div class="code-block">
            <span class="code-comment">// 创建8字节的ArrayBuffer</span>
            <span class="code-keyword">const</span> buffer = <span class="code-keyword">new</span> <span
              class="code-function">ArrayBuffer</span>(<span class="code-number">8</span>);

            <span class="code-comment">// 查看基本信息</span>
            console.log(<span class="code-string">'字节长度:'</span>, buffer.byteLength);
            console.log(<span class="code-string">'是否可调整大小:'</span>, buffer.resizable);
            console.log(<span class="code-string">'最大字节长度:'</span>, buffer.maxByteLength);

            <span class="code-comment">// 创建视图来访问数据</span>
            <span class="code-keyword">const</span> uint8View = <span class="code-keyword">new</span> <span
              class="code-function">Uint8Array</span>(buffer);
            <span class="code-keyword">const</span> uint16View = <span class="code-keyword">new</span> <span
              class="code-function">Uint16Array</span>(buffer);

            <span class="code-comment">// 写入数据</span>
            uint8View[<span class="code-number">0</span>] = <span class="code-number">0x12</span>;
            uint8View[<span class="code-number">1</span>] = <span class="code-number">0x34</span>;
            uint16View[<span class="code-number">1</span>] = <span class="code-number">0x5678</span>;

            <span class="code-comment">// 查看数据</span>
            console.log(<span class="code-string">'Uint8Array:'</span>, Array.from(uint8View));
            console.log(<span class="code-string">'Uint16Array:'</span>, Array.from(uint16View));
          </div>
          <div class="result-display" id="arraybufferResult">点击"运行ArrayBuffer示例"查看结果</div>
          <button class="btn btn-primary" onclick="runArrayBufferExample()">运行ArrayBuffer示例</button>
        </div>
      </div>

      <!-- DataView基础 -->
      <div class="section">
        <h2>📊 DataView 基础</h2>

        <div class="demo-section">
          <div class="demo-title">创建和使用DataView</div>
          <div class="code-block">
            <span class="code-comment">// 创建ArrayBuffer</span>
            <span class="code-keyword">const</span> buffer = <span class="code-keyword">new</span> <span
              class="code-function">ArrayBuffer</span>(<span class="code-number">16</span>);
            <span class="code-keyword">const</span> view = <span class="code-keyword">new</span> <span
              class="code-function">DataView</span>(buffer);

            <span class="code-comment">// 写入不同类型的数据</span>
            view.setUint8(<span class="code-number">0</span>, <span class="code-number">0x12</span>); <span
              class="code-comment">// 8位无符号整数</span>
            view.setUint16(<span class="code-number">1</span>, <span class="code-number">0x3456</span>, <span
              class="code-keyword">false</span>); <span class="code-comment">// 16位无符号整数(大端)</span>
            view.setUint32(<span class="code-number">3</span>, <span class="code-number">0x789ABCDE</span>, <span
              class="code-keyword">true</span>); <span class="code-comment">// 32位无符号整数(小端)</span>
            view.setFloat32(<span class="code-number">7</span>, <span class="code-number">3.14159</span>, <span
              class="code-keyword">false</span>); <span class="code-comment">// 32位浮点数(大端)</span>
            view.setFloat64(<span class="code-number">11</span>, <span class="code-number">2.71828</span>, <span
              class="code-keyword">true</span>); <span class="code-comment">// 64位浮点数(小端)</span>

            <span class="code-comment">// 读取数据</span>
            console.log(<span class="code-string">'Uint8(0):'</span>, view.getUint8(<span
              class="code-number">0</span>).toString(<span class="code-number">16</span>));
            console.log(<span class="code-string">'Uint16(1):'</span>, view.getUint16(<span
              class="code-number">1</span>, <span class="code-keyword">false</span>).toString(<span
              class="code-number">16</span>));
            console.log(<span class="code-string">'Uint32(3):'</span>, view.getUint32(<span
              class="code-number">3</span>, <span class="code-keyword">true</span>).toString(<span
              class="code-number">16</span>));
            console.log(<span class="code-string">'Float32(7):'</span>, view.getFloat32(<span
              class="code-number">7</span>, <span class="code-keyword">false</span>));
            console.log(<span class="code-string">'Float64(11):'</span>, view.getFloat64(<span
              class="code-number">11</span>, <span class="code-keyword">true</span>));
          </div>
          <div class="result-display" id="dataviewResult">点击"运行DataView示例"查看结果</div>
          <button class="btn btn-primary" onclick="runDataViewExample()">运行DataView示例</button>
        </div>
      </div>

      <!-- 字节序对比 -->
      <div class="section">
        <h2>🔄 字节序对比</h2>

        <div class="demo-section">
          <div class="demo-title">大端序 vs 小端序</div>
          <div class="code-block">
            <span class="code-comment">// 创建ArrayBuffer</span>
            <span class="code-keyword">const</span> buffer = <span class="code-keyword">new</span> <span
              class="code-function">ArrayBuffer</span>(<span class="code-number">4</span>);
            <span class="code-keyword">const</span> view = <span class="code-keyword">new</span> <span
              class="code-function">DataView</span>(buffer);

            <span class="code-comment">// 写入相同的32位整数</span>
            <span class="code-keyword">const</span> value = <span class="code-number">0x12345678</span>;
            view.setUint32(<span class="code-number">0</span>, value, <span class="code-keyword">false</span>); <span
              class="code-comment">// 大端序</span>

            <span class="code-comment">// 查看字节排列</span>
            <span class="code-keyword">const</span> uint8Array = <span class="code-keyword">new</span> <span
              class="code-function">Uint8Array</span>(buffer);
            console.log(<span class="code-string">'大端序字节排列:'</span>, Array.from(uint8Array).map(b => b.toString(<span
              class="code-number">16</span>).padStart(<span class="code-number">2</span>, <span
              class="code-string">'0'</span>)));

            <span class="code-comment">// 清空并写入小端序</span>
            <span class="code-keyword">for</span> (<span class="code-keyword">let</span> i = <span
              class="code-number">0</span>; i < buffer.byteLength; i++) { view.setUint8(i, <span class="code-number">
              0</span>);
              }
              view.setUint32(<span class="code-number">0</span>, value, <span class="code-keyword">true</span>); <span
                class="code-comment">// 小端序</span>

              console.log(<span class="code-string">'小端序字节排列:'</span>, Array.from(uint8Array).map(b => b.toString(<span
                class="code-number">16</span>).padStart(<span class="code-number">2</span>, <span
                class="code-string">'0'</span>)));

              <span class="code-comment">// 读取验证</span>
              console.log(<span class="code-string">'大端序读取:'</span>, view.getUint32(<span class="code-number">0</span>,
              <span class="code-keyword">false</span>).toString(<span class="code-number">16</span>));
              console.log(<span class="code-string">'小端序读取:'</span>, view.getUint32(<span class="code-number">0</span>,
              <span class="code-keyword">true</span>).toString(<span class="code-number">16</span>));
          </div>
          <div class="result-display" id="endianResult">点击"运行字节序示例"查看结果</div>
          <button class="btn btn-primary" onclick="runEndianExample()">运行字节序示例</button>
        </div>
      </div>

      <!-- 实际应用 -->
      <div class="section">
        <h2>💡 实际应用场景</h2>

        <div class="demo-section">
          <div class="demo-title">文件格式解析示例</div>
          <div class="code-block">
            <span class="code-comment">// 模拟WAV文件头解析</span>
            <span class="code-keyword">function</span> <span class="code-function">parseWAVHeader</span>(buffer) {
            <span class="code-keyword">const</span> view = <span class="code-keyword">new</span> <span
              class="code-function">DataView</span>(buffer);

            <span class="code-comment">// 检查RIFF标识</span>
            <span class="code-keyword">const</span> riff = <span class="code-function">String</span>.fromCharCode(
            view.getUint8(<span class="code-number">0</span>), view.getUint8(<span class="code-number">1</span>),
            view.getUint8(<span class="code-number">2</span>), view.getUint8(<span class="code-number">3</span>)
            );

            <span class="code-comment">// 检查WAVE标识</span>
            <span class="code-keyword">const</span> wave = <span class="code-function">String</span>.fromCharCode(
            view.getUint8(<span class="code-number">8</span>), view.getUint8(<span class="code-number">9</span>),
            view.getUint8(<span class="code-number">10</span>), view.getUint8(<span class="code-number">11</span>)
            );

            <span class="code-keyword">if</span> (riff !== <span class="code-string">'RIFF'</span> || wave !== <span
              class="code-string">'WAVE'</span>) {
            <span class="code-keyword">throw</span> <span class="code-keyword">new</span> <span
              class="code-function">Error</span>(<span class="code-string">'不是有效的WAV文件'</span>);
            }

            <span class="code-keyword">return</span> {
            fileSize: view.getUint32(<span class="code-number">4</span>, <span class="code-keyword">true</span>),
            sampleRate: view.getUint32(<span class="code-number">24</span>, <span class="code-keyword">true</span>),
            channels: view.getUint16(<span class="code-number">22</span>, <span class="code-keyword">true</span>),
            bitDepth: view.getUint16(<span class="code-number">34</span>, <span class="code-keyword">true</span>)
            };
            }

            <span class="code-comment">// 创建模拟的WAV文件头</span>
            <span class="code-keyword">const</span> wavHeader = <span class="code-keyword">new</span> <span
              class="code-function">ArrayBuffer</span>(<span class="code-number">44</span>);
            <span class="code-keyword">const</span> wavView = <span class="code-keyword">new</span> <span
              class="code-function">DataView</span>(wavHeader);

            <span class="code-comment">// 写入WAV文件头</span>
            <span class="code-function">String</span>.fromCharCode(<span class="code-string">'R'</span>, <span
              class="code-string">'I'</span>, <span class="code-string">'F'</span>, <span
              class="code-string">'F'</span>).split(<span class="code-string">''</span>).forEach((char, i) => {
            wavView.setUint8(i, char.charCodeAt(<span class="code-number">0</span>));
            });

            wavView.setUint32(<span class="code-number">4</span>, <span class="code-number">36</span>, <span
              class="code-keyword">true</span>); <span class="code-comment">// 文件大小</span>

            <span class="code-function">String</span>.fromCharCode(<span class="code-string">'W'</span>, <span
              class="code-string">'A'</span>, <span class="code-string">'V'</span>, <span
              class="code-string">'E'</span>).split(<span class="code-string">''</span>).forEach((char, i) => {
            wavView.setUint8(<span class="code-number">8</span> + i, char.charCodeAt(<span
              class="code-number">0</span>));
            });

            wavView.setUint32(<span class="code-number">24</span>, <span class="code-number">44100</span>, <span
              class="code-keyword">true</span>); <span class="code-comment">// 采样率</span>
            wavView.setUint16(<span class="code-number">22</span>, <span class="code-number">2</span>, <span
              class="code-keyword">true</span>); <span class="code-comment">// 声道数</span>
            wavView.setUint16(<span class="code-number">34</span>, <span class="code-number">16</span>, <span
              class="code-keyword">true</span>); <span class="code-comment">// 位深度</span>

            <span class="code-comment">// 解析WAV头</span>
            <span class="code-keyword">const</span> wavInfo = <span
              class="code-function">parseWAVHeader</span>(wavHeader);
            console.log(<span class="code-string">'WAV文件信息:'</span>, wavInfo);
          </div>
          <div class="result-display" id="wavResult">点击"运行WAV解析示例"查看结果</div>
          <button class="btn btn-primary" onclick="runWAVExample()">运行WAV解析示例</button>
        </div>
      </div>

      <!-- 交互式演示 -->
      <div class="section">
        <h2>🎮 交互式演示</h2>

        <div class="interactive-demo">
          <div class="input-group">
            <label for="dataType">数据类型:</label>
            <select id="dataType">
              <option value="uint8">Uint8 (8位无符号整数)</option>
              <option value="uint16">Uint16 (16位无符号整数)</option>
              <option value="uint32">Uint32 (32位无符号整数)</option>
              <option value="int8">Int8 (8位有符号整数)</option>
              <option value="int16">Int16 (16位有符号整数)</option>
              <option value="int32">Int32 (32位有符号整数)</option>
              <option value="float32">Float32 (32位浮点数)</option>
              <option value="float64">Float64 (64位浮点数)</option>
            </select>
          </div>

          <div class="input-group">
            <label for="dataValue">数值:</label>
            <input type="text" id="dataValue" placeholder="输入数值" value="12345">
          </div>

          <div class="input-group">
            <label for="endianness">字节序:</label>
            <select id="endianness">
              <option value="false">大端序 (Big Endian)</option>
              <option value="true">小端序 (Little Endian)</option>
            </select>
          </div>

          <button class="btn btn-primary" onclick="runInteractiveDemo()">运行演示</button>
          <button class="btn btn-secondary" onclick="clearInteractive()">清空</button>

          <div id="interactiveResult" class="result-display">选择数据类型和数值，然后点击运行演示</div>
        </div>
      </div>

      <!-- 内存可视化 -->
      <div class="section">
        <h2>🧠 内存可视化</h2>

        <div class="demo-section">
          <div class="demo-title">ArrayBuffer内存布局</div>
          <div class="memory-visualization" id="memoryVisualization">
            <div class="memory-row">
              <div class="memory-cell header">地址</div>
              <div class="memory-cell header">0x00</div>
              <div class="memory-cell header">0x01</div>
              <div class="memory-cell header">0x02</div>
              <div class="memory-cell header">0x03</div>
              <div class="memory-cell header">0x04</div>
              <div class="memory-cell header">0x05</div>
              <div class="memory-cell header">0x06</div>
              <div class="memory-cell header">0x07</div>
            </div>
            <div class="memory-row">
              <div class="memory-cell header">数据</div>
              <div class="memory-cell data" id="mem0">00</div>
              <div class="memory-cell data" id="mem1">00</div>
              <div class="memory-cell data" id="mem2">00</div>
              <div class="memory-cell data" id="mem3">00</div>
              <div class="memory-cell data" id="mem4">00</div>
              <div class="memory-cell data" id="mem5">00</div>
              <div class="memory-cell data" id="mem6">00</div>
              <div class="memory-cell data" id="mem7">00</div>
            </div>
          </div>
          <button class="btn btn-primary" onclick="updateMemoryVisualization()">更新内存视图</button>
        </div>
      </div>

      <!-- 总结 -->
      <div class="section">
        <h2>📝 总结</h2>

        <div class="demo-section">
          <h3>ArrayBuffer vs DataView 选择指南</h3>

          <div class="code-block">
            <span class="code-comment">// 使用ArrayBuffer + TypedArray 当:</span>
            <span class="code-comment">// 1. 处理同类型数据</span>
            <span class="code-comment">// 2. 需要高性能</span>
            <span class="code-comment">// 3. 字节序不重要</span>
            <span class="code-keyword">const</span> buffer1 = <span class="code-keyword">new</span> <span
              class="code-function">ArrayBuffer</span>(<span class="code-number">1024</span>);
            <span class="code-keyword">const</span> uint8Array = <span class="code-keyword">new</span> <span
              class="code-function">Uint8Array</span>(buffer1);

            <span class="code-comment">// 使用DataView 当:</span>
            <span class="code-comment">// 1. 处理混合数据类型</span>
            <span class="code-comment">// 2. 需要控制字节序</span>
            <span class="code-comment">// 3. 解析文件格式</span>
            <span class="code-comment">// 4. 网络协议实现</span>
            <span class="code-keyword">const</span> buffer2 = <span class="code-keyword">new</span> <span
              class="code-function">ArrayBuffer</span>(<span class="code-number">1024</span>);
            <span class="code-keyword">const</span> view = <span class="code-keyword">new</span> <span
              class="code-function">DataView</span>(buffer2);
          </div>
        </div>
      </div>
    </div>
  </div>

  <script>
    // ArrayBuffer示例
    function runArrayBufferExample() {
      const buffer = new ArrayBuffer(8);

      const uint8View = new Uint8Array(buffer);
      const uint16View = new Uint16Array(buffer);

      uint8View[0] = 0x12;
      uint8View[1] = 0x34;
      uint16View[1] = 0x5678;

      const result = `ArrayBuffer 基本信息:
字节长度: ${buffer.byteLength}
是否可调整大小: ${buffer.resizable}
最大字节长度: ${buffer.maxByteLength}

数据内容:
Uint8Array: [${Array.from(uint8View).map(b => '0x' + b.toString(16).padStart(2, '0')).join(', ')}]
Uint16Array: [${Array.from(uint16View).map(b => '0x' + b.toString(16).padStart(4, '0')).join(', ')}]`;

      document.getElementById('arraybufferResult').textContent = result;
    }

    // DataView示例
    function runDataViewExample() {
      const buffer = new ArrayBuffer(16);
      const view = new DataView(buffer);

      view.setUint8(0, 0x12);
      view.setUint16(1, 0x3456, false);
      view.setUint32(3, 0x789ABCDE, true);
      view.setFloat32(7, 3.14159, false);
      view.setFloat64(11, 2.71828, true);

      const result = `DataView 数据读写:
Uint8(0): 0x${view.getUint8(0).toString(16).padStart(2, '0')}
Uint16(1): 0x${view.getUint16(1, false).toString(16).padStart(4, '0')}
Uint32(3): 0x${view.getUint32(3, true).toString(16).padStart(8, '0')}
Float32(7): ${view.getFloat32(7, false)}
Float64(11): ${view.getFloat64(11, true)}`;

      document.getElementById('dataviewResult').textContent = result;
    }

    // 字节序示例
    function runEndianExample() {
      const buffer = new ArrayBuffer(4);
      const view = new DataView(buffer);

      const value = 0x12345678;
      view.setUint32(0, value, false);

      const uint8Array = new Uint8Array(buffer);
      const bigEndian = Array.from(uint8Array).map(b => b.toString(16).padStart(2, '0'));

      for (let i = 0; i < buffer.byteLength; i++) {
        view.setUint8(i, 0);
      }
      view.setUint32(0, value, true);

      const littleEndian = Array.from(uint8Array).map(b => b.toString(16).padStart(2, '0'));

      const result = `字节序对比 (值: 0x${value.toString(16).toUpperCase()}):
大端序字节排列: [${bigEndian.join(', ')}]
小端序字节排列: [${littleEndian.join(', ')}]

读取验证:
大端序读取: 0x${view.getUint32(0, false).toString(16).toUpperCase()}
小端序读取: 0x${view.getUint32(0, true).toString(16).toUpperCase()}`;

      document.getElementById('endianResult').textContent = result;
    }

    // WAV解析示例
    function runWAVExample() {
      function parseWAVHeader(buffer) {
        const view = new DataView(buffer);

        const riff = String.fromCharCode(
          view.getUint8(0), view.getUint8(1),
          view.getUint8(2), view.getUint8(3)
        );

        const wave = String.fromCharCode(
          view.getUint8(8), view.getUint8(9),
          view.getUint8(10), view.getUint8(11)
        );

        if (riff !== 'RIFF' || wave !== 'WAVE') {
          throw new Error('不是有效的WAV文件');
        }

        return {
          fileSize: view.getUint32(4, true),
          sampleRate: view.getUint32(24, true),
          channels: view.getUint16(22, true),
          bitDepth: view.getUint16(34, true)
        };
      }

      const wavHeader = new ArrayBuffer(44);
      const wavView = new DataView(wavHeader);

      String.fromCharCode('R', 'I', 'F', 'F').split('').forEach((char, i) => {
        wavView.setUint8(i, char.charCodeAt(0));
      });

      wavView.setUint32(4, 36, true);

      String.fromCharCode('W', 'A', 'V', 'E').split('').forEach((char, i) => {
        wavView.setUint8(8 + i, char.charCodeAt(0));
      });

      wavView.setUint32(24, 44100, true);
      wavView.setUint16(22, 2, true);
      wavView.setUint16(34, 16, true);

      const wavInfo = parseWAVHeader(wavHeader);

      const result = `WAV文件解析结果:
文件大小: ${wavInfo.fileSize} 字节
采样率: ${wavInfo.sampleRate} Hz
声道数: ${wavInfo.channels}
位深度: ${wavInfo.bitDepth} 位`;

      document.getElementById('wavResult').textContent = result;
    }

    // 交互式演示
    function runInteractiveDemo() {
      const dataType = document.getElementById('dataType').value;
      const dataValue = parseFloat(document.getElementById('dataValue').value);
      const endianness = document.getElementById('endianness').value === 'true';

      if (isNaN(dataValue)) {
        document.getElementById('interactiveResult').textContent = '请输入有效的数值';
        return;
      }

      const buffer = new ArrayBuffer(8);
      const view = new DataView(buffer);

      try {
        switch (dataType) {
          case 'uint8':
            view.setUint8(0, dataValue);
            break;
          case 'uint16':
            view.setUint16(0, dataValue, endianness);
            break;
          case 'uint32':
            view.setUint32(0, dataValue, endianness);
            break;
          case 'int8':
            view.setInt8(0, dataValue);
            break;
          case 'int16':
            view.setInt16(0, dataValue, endianness);
            break;
          case 'int32':
            view.setInt32(0, dataValue, endianness);
            break;
          case 'float32':
            view.setFloat32(0, dataValue, endianness);
            break;
          case 'float64':
            view.setFloat64(0, dataValue, endianness);
            break;
        }

        const uint8Array = new Uint8Array(buffer);
        const hexBytes = Array.from(uint8Array).map(b => '0x' + b.toString(16).padStart(2, '0')).join(' ');

        const result = `数据类型: ${dataType}
数值: ${dataValue}
字节序: ${endianness ? '小端序' : '大端序'}
字节表示: ${hexBytes}
字节数: ${getDataTypeSize(dataType)}`;

        document.getElementById('interactiveResult').textContent = result;

      } catch (error) {
        document.getElementById('interactiveResult').textContent = `错误: ${error.message}`;
      }
    }

    function getDataTypeSize(dataType) {
      const sizes = {
        'uint8': 1, 'int8': 1,
        'uint16': 2, 'int16': 2,
        'uint32': 4, 'int32': 4,
        'float32': 4, 'float64': 8
      };
      return sizes[dataType] || 0;
    }

    function clearInteractive() {
      document.getElementById('dataValue').value = '';
      document.getElementById('interactiveResult').textContent = '选择数据类型和数值，然后点击运行演示';
    }

    // 内存可视化
    function updateMemoryVisualization() {
      const buffer = new ArrayBuffer(8);
      const view = new DataView(buffer);

      // 写入一些示例数据
      view.setUint16(0, 0x1234, false);  // 大端序
      view.setUint32(2, 0x567890AB, true); // 小端序
      view.setUint16(6, 0xCDEF, false);  // 大端序

      const uint8Array = new Uint8Array(buffer);

      // 更新内存视图
      for (let i = 0; i < 8; i++) {
        const cell = document.getElementById(`mem${i}`);
        cell.textContent = uint8Array[i].toString(16).padStart(2, '0').toUpperCase();
        cell.style.background = '#e8f5e8';
      }
    }

    // 页面加载完成
    window.addEventListener('load', function () {
      console.log('ArrayBuffer 和 DataView 演示页面已加载完成');
      updateMemoryVisualization();
    });
  </script>
</body>

</html>